package com.wswy.wzcx.widget;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.blankj.utilcode.util.SizeUtils;
import com.wswy.wzcx.R;

public class LoadingStatusView extends View {

    private static final String TAG = "LoadingStatusView";

    private int themeColor;

    private int progressColor;    //进度颜色
    private int loadSuccessColor;    //成功的颜色
    private int loadFailureColor;   //失败的颜色
    private float progressWidth;    //进度宽度
    private float progressRadius;   //圆环半径

    private Paint mPaint;
    private StatusEnum mStatus;     //状态

    private float startAngle = 0;
    private int sweepAngle = 160;

    //追踪Path的坐标
    private PathMeasure mPathMeasure;
    //画圆的Path
    private Path mPathCircle;
    //截取PathMeasure中的path
    private Path mPathCircleDst;
    private Path successPath;
    private Path failurePathLeft;
    private Path failurePathRight;

    private ValueAnimator circleAnimator;

    private ValueAnimator pendingAnimator;
    private int pendingValue;
    private boolean pendingStatus= false;

    private float circleValue;
    private float successValue;
    private float failValueRight;
    private float failValueLeft;

    private RectF rectF = new RectF();

    private SweepGradient gradient;
    private Matrix rotateMatrix = new Matrix();

    public LoadingStatusView(Context context) {
        this(context, null);
    }

    public LoadingStatusView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LoadingStatusView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);


        themeColor = ContextCompat.getColor(context, R.color.colorPrimary);
        progressColor = Color.WHITE;
        loadSuccessColor = progressColor;
        loadFailureColor = progressColor;
        progressWidth = SizeUtils.dp2px(2);
        progressRadius = SizeUtils.dp2px(10);

//        progressWidth = 8;
//        progressRadius = 50;

        initPaint();
        initPath();
        initAnim();
    }

    private void initPaint() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(progressColor);
        mPaint.setStyle(Paint.Style.STROKE);
        //mPaint.setDither(true);
        //mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(progressWidth);
        mPaint.setStrokeCap(Paint.Cap.ROUND);    //设置画笔为圆角笔触
        mPaint.setAlpha(255);
    }

    private void initPath() {
        mPathCircle = new Path();
        mPathMeasure = new PathMeasure();
        mPathCircleDst = new Path();
        successPath = new Path();
        failurePathLeft = new Path();
        failurePathRight = new Path();
    }

    private void initAnim() {
        circleAnimator = ValueAnimator.ofFloat(0, 1);
        circleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                circleValue = (float) animation.getAnimatedValue();
                invalidate();
            }
        });



        pendingAnimator = ValueAnimator.ofInt(255,0);
        pendingAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                pendingStatus = false;

                if (loadingAnimator != null){
                    loadingAnimator.cancel();
                    loadingAnimator = null;
                }
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                pendingStatus = true;
            }
        });
        pendingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                pendingValue = (int) animation.getAnimatedValue();
                invalidate();
            }
        });


    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        
        canvas.translate(getPaddingLeft(), getPaddingTop());   //将当前画布的点移到getPaddingLeft,getPaddingTop,后面的操作都以该点作为参照点
        if (mStatus == StatusEnum.Loading || pendingStatus) {    //正在加载
            
            
            rectF.set(progressWidth, progressWidth, getWidth()-progressWidth, getHeight()-progressWidth);

            if (gradient == null){

//                int[] colors= {Color.parseColor("#ff285BF6"),
//                    Color.parseColor("#ff0CC79B"),
//                    Color.WHITE,Color.parseColor("#ff285BF6"),
//                    Color.parseColor("#ff0CC79B"),
//                    Color.WHITE
//                };

                int[] colors= {themeColor,
                    Color.WHITE,themeColor,
                    Color.WHITE
                };

                float[] pos = {0,0.5f,0.5f,1f};
                gradient = new SweepGradient(rectF.centerX(),rectF.centerY(),colors,pos);
                
            }

            rotateMatrix.setRotate(startAngle - 10, rectF.centerX(), rectF.centerY());
            gradient.setLocalMatrix(rotateMatrix);
            mPaint.setShader(gradient);

            mPaint.setColor(Color.WHITE);

            if (pendingStatus){
                mPaint.setAlpha(pendingValue);
            }


            //mPaint.setXfermode(xfermode);

            //int save = canvas.save();
            //canvas.drawARGB(0xff,28,0x5b,0xf6);
            canvas.drawArc(rectF, startAngle, sweepAngle, false, mPaint);
            canvas.drawArc(rectF, startAngle + 180, sweepAngle, false, mPaint);

            //canvas.restoreToCount(save);

        } else if (mStatus == StatusEnum.LoadSuccess) {     //加载成功


            mPaint.setShader(null);

            mPaint.setColor(loadSuccessColor);
            mPathCircle.addCircle(getWidth() / 2, getWidth() / 2, progressRadius, Path.Direction.CW);
            mPathMeasure.setPath(mPathCircle, false);
            mPathMeasure.getSegment(0, circleValue * mPathMeasure.getLength(), mPathCircleDst, true);   //截取path并保存到mPathCircleDst中


            if (circleValue != 1){
                canvas.rotate(180,getWidth()/2,getHeight()/2);

                canvas.drawPath(mPathCircleDst, mPaint);
            }


            if (circleValue == 1) {      //表示圆画完了,可以钩了
                successPath.moveTo(getWidth() * 0.3f, getWidth() / 2);
                successPath.lineTo(getWidth()  * 0.41f, getHeight() * 0.6f);
                successPath.lineTo(getWidth() / 3 * 2, getWidth() / 5 * 2);
                mPathMeasure.nextContour();
                mPathMeasure.setPath(successPath, false);
                mPathMeasure.getSegment(0, successValue * mPathMeasure.getLength(), mPathCircleDst, true);
                canvas.drawPath(mPathCircleDst, mPaint);
            }

        } else {      //加载失败


            mPaint.setShader(null);

            mPaint.setColor(loadFailureColor);
            mPathCircle.addCircle(getWidth() / 2, getWidth() / 2, progressRadius, Path.Direction.CW);
            mPathMeasure.setPath(mPathCircle, false);
            mPathMeasure.getSegment(0, circleValue * mPathMeasure.getLength(), mPathCircleDst, true);

            if (circleValue != 1){
                canvas.rotate(180,getWidth()/2,getHeight()/2);

                canvas.drawPath(mPathCircleDst, mPaint);
            }

            if (circleValue == 1) {  //表示圆画完了,可以画叉叉的右边部分
                failurePathRight.moveTo(getWidth() / 3 * 2, getWidth() / 3);
                failurePathRight.lineTo(getWidth() / 3, getWidth() / 3 * 2);
                mPathMeasure.nextContour();
                mPathMeasure.setPath(failurePathRight, false);
                mPathMeasure.getSegment(0, failValueRight * mPathMeasure.getLength(), mPathCircleDst, true);
                canvas.drawPath(mPathCircleDst, mPaint);
            }

            if (failValueRight == 1) {    //表示叉叉的右边部分画完了,可以画叉叉的左边部分
                failurePathLeft.moveTo(getWidth() / 3, getWidth() / 3);
                failurePathLeft.lineTo(getWidth() / 3 * 2, getWidth() / 3 * 2);
                mPathMeasure.nextContour();
                mPathMeasure.setPath(failurePathLeft, false);
                mPathMeasure.getSegment(0, failValueLeft * mPathMeasure.getLength(), mPathCircleDst, true);
                canvas.drawPath(mPathCircleDst, mPaint);
            }

        }
    }

    //重制路径
    private void resetPath() {
        successValue = 0;
        circleValue = 0;
        failValueLeft = 0;
        failValueRight = 0;
        mPathCircle.reset();
        mPathCircleDst.reset();
        failurePathLeft.reset();
        failurePathRight.reset();
        successPath.reset();
    }

    private void setStatus(StatusEnum status) {
        mStatus = status;
    }

    private ValueAnimator loadingAnimator;

    public void dismiss(){
        if (loadingAnimator != null){
            loadingAnimator.cancel();
            loadingAnimator = null;
        }
    }

    public void loadLoading() {
        setStatus(StatusEnum.Loading);
        //invalidate();

        if (loadingAnimator != null){
            loadingAnimator.cancel();
            loadingAnimator = null;
        }

        loadingAnimator = ValueAnimator.ofFloat(0f, 180f);
        loadingAnimator.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                startAngle = (float) animation.getAnimatedValue();
                postInvalidateOnAnimation();
            }
        });
        loadingAnimator.setInterpolator(new LinearInterpolator());
        loadingAnimator.setRepeatCount(ValueAnimator.INFINITE);
        loadingAnimator.setRepeatMode(ValueAnimator.RESTART);
        loadingAnimator.setDuration(400);
        loadingAnimator.start();
    }

    public void loadSuccess(OnAnimEndCallback callback) {
        resetPath();
        setStatus(StatusEnum.LoadSuccess);
        startSuccessAnim(callback);
    }

    public void loadFailure(OnAnimEndCallback callback) {
        resetPath();
        setStatus(StatusEnum.LoadFailure);
        startFailAnim(callback);
    }

    public void loadEnd(){
        resetPath();
        dismiss();
        pendingStatus = false;
        setStatus(StatusEnum.LoadEnd);
        postInvalidateOnAnimation();
        setVisibility(GONE);
    }

    private void startSuccessAnim(final OnAnimEndCallback callback) {
        ValueAnimator success = ValueAnimator.ofFloat(0f, 1.0f);
        success.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                successValue = (float) animation.getAnimatedValue();
                postInvalidateOnAnimation();
            }
        });
        //组合动画,一先一后执行
        AnimatorSet animatorSet = new AnimatorSet();

//        animatorSet.play(success).after(circleAnimator);
        animatorSet.playSequentially(pendingAnimator,circleAnimator,success);
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                if (callback != null){
                    callback.onEnd();
                }
            }
        });
        animatorSet.setDuration(500);
        animatorSet.start();
    }

    private void startFailAnim(final OnAnimEndCallback callback) {
        ValueAnimator failLeft = ValueAnimator.ofFloat(0f, 1.0f);
        failLeft.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                failValueRight = (float) animation.getAnimatedValue();
                postInvalidateOnAnimation();
            }
        });
        ValueAnimator failRight = ValueAnimator.ofFloat(0f, 1.0f);
        failRight.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                failValueLeft = (float) animation.getAnimatedValue();
                postInvalidateOnAnimation();
            }
        });
        //组合动画,一先一后执行
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playSequentially(pendingAnimator,circleAnimator,failLeft,failRight);
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                if (callback != null){
                    callback.onEnd();
                }
            }
        });
        //animatorSet.play(failLeft).after(circleAnimator).after(pendingAnimator).before(failRight);
        //animatorSet.setDuration(800);
        animatorSet.start();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width;
        int height;
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);

        if (mode == MeasureSpec.EXACTLY) {
            width = size;
        } else {
            width = (int) (2f * progressRadius + progressWidth + getPaddingLeft() + getPaddingRight());
        }

        mode = MeasureSpec.getMode(heightMeasureSpec);
        size = MeasureSpec.getSize(heightMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            height = size;
        } else {
            height = (int) (2f * progressRadius + progressWidth + getPaddingTop() + getPaddingBottom());
        }

        setMeasuredDimension(width, height);

    }


    private enum StatusEnum {
        Loading,
        LoadSuccess,
        LoadFailure,
        LoadEnd
    }


    interface OnAnimEndCallback{
        void onEnd();
    }

}